﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Red.GameData.Raw
{
    partial class DataObject
    {
        /// <summary>
        /// Load object from XML
        /// Automatically registers the object in the file
        /// All errors are reported through the "log" interface
        /// </summary>
        /// <param name="file">File to add the loaded object to</param>
        /// <param name="log">Error/progress reporting log</param>
        /// <param name="xml">XML node to load the object from</param>
        public static DataObject LoadFromNode(DataFile file, IGenericFileErrorReporter log, XmlNode xml)
        {
            // get id
            var id = Raw.Utils.AttrID(xml, "id");
            if (id == Guid.Empty)
            {
                log.Error("Missing or invalid object id");
                return null;
            }

            // we need at least base object
            var baseId = Raw.Utils.AttrID(xml, "base");
            var className = Raw.Utils.Attr(xml, "class");
            if (className == "" && baseId == Guid.Empty)
            {
                log.Error(String.Format("Object {0} has no baseId and class specified. There's no way to tell what the object is.", id.ToString()));
                return null;
            }

            // load the parent ID
            var parentId = Raw.Utils.AttrID(xml, "parent");

            // create object
            DataObject ret = new DataObject(file, id, baseId, parentId, className);

            // additional attributes
            ret._isAbstract = Raw.Utils.Attr(xml, "abstract", false);

            // load properties
            foreach (var item in xml.ChildNodes)
            {
                var xmlNode = item as XmlNode;
                if (xmlNode != null)
                {
                    if (xmlNode.Name == "property")
                    {
                        var prop = DataProperty.LoadFromNode(ret, log, xmlNode);
                        if (prop != null)
                        {
                            ret._properties.Add(prop);
                        }
                    }
                }
            }

            return ret;
        }

        /// <summary>
        /// Save object to XML document
        /// </summary>
        /// <param name="xml"></param>
        public void SaveToNode(XmlElement xml)
        {
            xml.SetAttribute("id", Raw.Utils.FormatGuid(ID));

            if (BaseID != Guid.Empty)
                xml.SetAttribute("base", Raw.Utils.FormatGuid(BaseID));

            if (ParentID != Guid.Empty)
                xml.SetAttribute("parent", Raw.Utils.FormatGuid(ParentID));            

            if (ClassName != "")
                xml.SetAttribute("class", ClassName);

            if (_isAbstract != false)
                xml.SetAttribute("abstract", "true");

            foreach (var prop in _properties)
            {
                var childXml = xml.OwnerDocument.CreateElement("property");
                xml.AppendChild(childXml);

                prop.SaveToNode(childXml);
            }

            // reset object flag
            // NOTE: this is not totally consistent but we relay more on the DataFile IsModified flag
            _isModified = false;
        }

    }
}
